# -*- encoding: utf-8 -*-

"""
@File:      tc_libmnl_libmnl_func_001.py
@Time:      2024/03/29 14:33:20
@Author:    chenchunhu
@Version:   1.0
@Contact:   wb-cch358909@alibaba-inc.com
@License:   Mulan PSL v2
@Modify:    chenchunhu
"""

from common.basetest import LocalTest

class Test(LocalTest):
    """
    See tc_libmnl_libmnl_func_001.yaml for details

    :avocado: tags=P2,noarch,local,fix
    """

    PARAM_DIC = {"pkg_name": "libmnl libmnl-devel gcc"}
    def setUp(self):
        super().setUp(self.PARAM_DIC)
        cmdline = '''cat >libmnl_test1.c<<"EOF"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <libmnl/libmnl.h>
#include <linux/netlink.h>
#include <linux/genetlink.h>

#define MNL_BUFFER_SIZE MNL_SOCKET_BUFFER_SIZE // 将 buffer 的大小设为 MNL 推荐的大小

int main(void) {
    struct mnl_socket *sock;
    char buf[MNL_BUFFER_SIZE]; // 为 Netlink 消息分配负载空间
    struct nlmsghdr *nlh;
    unsigned int seq, portid;
    int ret;

    // 创建和绑定 Netlink 套接字
    sock = mnl_socket_open(NETLINK_GENERIC);
    if (sock == NULL) {
        perror("mnl_socket_open");
        return EXIT_FAILURE;
    }
    // 绑定套接字
    if (mnl_socket_bind(sock, 0, MNL_SOCKET_AUTOPID) < 0) {
        perror("mnl_socket_bind");
        mnl_socket_close(sock);
        return EXIT_FAILURE;
    }

    // 准备发送的 Netlink 消息
    seq = time(NULL); // 使用当前时间作为消息序列号
    portid = mnl_socket_get_portid(sock); // 获取端口号用于消息确认

    // 初始化 Netlink 消息头部
    nlh = mnl_nlmsg_put_header(buf);
    nlh->nlmsg_type = NLMSG_NOOP; // 消息类型无操作 (NLMSG_NOOP)，只做测试
    nlh->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK; // 请求 Netlink 回应
    nlh->nlmsg_seq = seq;
    nlh->nlmsg_pid = portid;

    // 使用 libmnl 发送消息
    if (mnl_socket_sendto(sock, nlh, nlh->nlmsg_len) < 0) {
        perror("mnl_socket_send");
        mnl_socket_close(sock);
        return EXIT_FAILURE;
    }

    // 接收来自内核的回应
    ret = mnl_socket_recvfrom(sock, buf, sizeof(buf));
    if (ret == -1) {
        perror("mnl_socket_recvfrom");
        mnl_socket_close(sock);
        return EXIT_FAILURE;
    }

    // 处理响应消息
    if (mnl_cb_run(buf, ret, seq, portid, NULL, NULL) < 0) {
        perror("mnl_cb_run");
        mnl_socket_close(sock);
        return EXIT_FAILURE;
    }

    // 关闭 socket
    mnl_socket_close(sock);
    printf("Netlink communication test completed successfully.\\n");

    return EXIT_SUCCESS;
}
EOF'''
        self.cmd(cmdline)


    def test(self):
        self.cmd("gcc -o libmnl_test1 libmnl_test1.c -lmnl")
        code, libmnl_result = self.cmd("./libmnl_test1")
        self.assertIn("Netlink communication test completed successfully", libmnl_result)

    def tearDown(self):
        super().tearDown(self.PARAM_DIC)
        self.cmd("rm -rf libmnl_test1.c libmnl_test1")
